﻿
package com.youdo.ad.core {

	import flash.geom.Rectangle;
	import flash.display.DisplayObjectContainer;
	import flash.utils.Dictionary;

	import org.osflash.signals.Signal;
	import org.osflash.signals.DeluxeSignal;
	import org.osflash.signals.events.GenericEvent;
	/**
	 * @author Shanghai Sun
	 */
	public class XAdManager {

		protected var adSlotHashMap : Dictionary;
		//
		private var proxied : Object;
		/**
		 * @see #signal4ScanSlotsCompleted
		 */
		public var signal4RequestCompleted : Signal;
		/**
		 * @see #signal4RequestCompleted
		 */
		public var signal4ScanSlotsCompleted : Signal;

		/**
		 * @see #signal4SlotEnd
		 * @see #signal4SlotStateChange
		 * @see #signal4SlotPreloaded
		 */
		public var signal4SlotStart : DeluxeSignal;
		/**
		 * @see #signal4SlotStart
		 * @see #signal4SlotStateChange
		 * @see #signal4SlotPreloaded
		 */
		public var signal4SlotEnd : DeluxeSignal;
		/**
		 * @see #signal4SlotStart
		 * @see #signal4SlotEnd
		 * @see #signal4SlotPreloaded
		 */
		public var signal4SlotStateChange : DeluxeSignal;
		/**
		 * @see #signal4SlotStart
		 * @see #signal4SlotEnd
		 * @see #signal4SlotStateChange
		 */
		public var signal4SlotPreloaded : DeluxeSignal;
		

		/**
		 * 
		 */
		public function XAdManager(proxiedObj : Object) {
			//
			this.adSlotHashMap = new Dictionary();
			//
			this.signal4RequestCompleted = new Signal( Boolean );
			this.signal4ScanSlotsCompleted = new Signal( Boolean );
			//
			this.signal4SlotStart = new DeluxeSignal(this, GenericEvent, XAdSlot);
			this.signal4SlotEnd = new DeluxeSignal(this, GenericEvent, XAdSlot);
			this.signal4SlotStateChange = new DeluxeSignal(this, GenericEvent, XAdSlot);
			this.signal4SlotPreloaded = new DeluxeSignal(this, GenericEvent, XAdSlot);
			//
			
			this.proxied = (proxiedObj != null) ? proxiedObj : {};
			// 
			this.proxied.signal4SlotStart.add(this.handleSlotStart);
			this.proxied.signal4SlotEnd.add(this.handleSlotEnd);
			this.proxied.signal4SlotStateChange.add(this.handleSlotStateChange);
			this.proxied.signal4SlotPreloaded.add(this.handleSlotPreloaded);
			//
			this.proxied.signal4RequestCompleted.addOnce( this.handleRequestCompleted );
			// this.proxied.signal4ScanSlotsCompleted.addOnce(this.handleScanPageSlotsCompledted);
			
		}
		private function handleSlotStart(evt:*, slot:*) : void {
			this.signal4SlotStart.dispatch(new GenericEvent(), this.convert2AdSlot(slot));
		}
		private function handleSlotEnd(evt:*, slot:*) : void {
			this.signal4SlotEnd.dispatch(new GenericEvent(), this.convert2AdSlot(slot));
		}
		private function handleSlotStateChange(evt:*, slot:*) : void {
			this.signal4SlotStateChange.dispatch(new GenericEvent(), this.convert2AdSlot(slot));
		}
		private function handleSlotPreloaded(evt:*, slot:*) : void {
			this.signal4SlotPreloaded.dispatch(new GenericEvent(), this.convert2AdSlot(slot));
		}

		/**
		 * @see getVideoPlayerNonTemporalSlots()
		 * @see getSiteSectionNonTemporalSlots
		 * @see getSlotById()
		 * @see getActiveSlots()
		 */
		public function getTemporalSlots() : Vector.<XAdSlot> {
			var results : Vector.<XAdSlot> = new Vector.<XAdSlot>();
			var slots : Array = this.proxied.getTemporalSlots().slice();
			while (slots.length) {
				results.push( this.convert2AdSlot( slots.pop() ) );
			}
			return results;
		}

		/**
		 * @see getTemporalSlots
		 * @see getSiteSectionNonTemporalSlots
		 * @see getSlotById()
		 * @see getActiveSlots()
		 */
		public function getVideoPlayerNonTemporalSlots() : Vector.<XAdSlot> {
			var results : Vector.<XAdSlot> = new Vector.<XAdSlot>();
			var slots : Array = this.proxied.getVideoPlayerNonTemporalSlots().slice();
			while (slots.length) {
				results.push( this.convert2AdSlot( slots.pop() ) );
			}
			return results;
		}

		/**
		 * @see getTemporalSlots
		 * @see getVideoPlayerNonTemporalSlots()
		 * @see getSlotById()
		 * @see getActiveSlots()
		 */
		public function getSiteSectionNonTemporalSlots() : Vector.<XAdSlot> {
			var results : Vector.<XAdSlot> = new Vector.<XAdSlot>();
			var slots : Array = this.proxied.getSiteSectionNonTemporalSlots().slice();
			while (slots.length) {
				results.push( this.convert2AdSlot( slots.pop() ) );
			}
			return results;
		}

		/**
		 * @see getTemporalSlots
		 * @see getVideoPlayerNonTemporalSlots()
		 * @see getSiteSectionNonTemporalSlots
		 * @see getActiveSlots()
		 */
		public function getSlotById(id : String) : XAdSlot {
			var slot : * = this.proxied.getSlotById( id );
			return slot ? (this.convert2AdSlot( slot )) : (null);
		}

		/**
		 * @see getTemporalSlots
		 * @see getVideoPlayerNonTemporalSlots()
		 * @see getSiteSectionNonTemporalSlots
		 */
		public function getActiveSlots() : Vector.<XAdSlot> {
			var results : Vector.<XAdSlot> = new Vector.<XAdSlot>();
			var slots : Array = this.proxied.getActiveSlots().slice();
			while (slots.length) {
				results.push( this.convert2AdSlot( slots.pop() ) );
			}
			return results;
		}

		public function setAdVolume(vol : uint) : void {
			this.proxied.setAdVolume( vol );
		}

		public function getAdVolume() : uint {
			return this.proxied.getAdVolume();
		}

		/**
		 * 
		 */
		public function registerVideoDisplay(container : DisplayObjectContainer) : void {
			this.proxied.registerVideoDisplay( container );
		}

		/**
		 * 
		 */
		public function registerPlayheadTimeCallback(cb : Function) : void {
			this.proxied.registerPlayheadTimeCallback( cb );
		}

		/**
		 * add
		 * 
		 * @param id
		 * @param container
		 * @param slotRect
		 * @param acceptCompanion
		 */
		public function addVideoPlayerNonTemporalSlot(id : String, container : DisplayObjectContainer, slotRect : Rectangle, acceptCompanion : Boolean = true) : XAdSlot {
			var slot : * = this.proxied.addVideoPlayerNonTemporalSlot( id, container, slotRect, acceptCompanion );
			return slot ? (this.convert2AdSlot( slot )) : (null);
		}

		/**
		 * scan page solts
		 * 
		 * @param timeout
		 */
		public function scanPageSlots(timeout : Number = 0) : void {
			this.proxied.scanPageSlots( timeout );
		}

		private function handleScanPageSlotsCompledted(success : Boolean) : void {
			this.signal4ScanSlotsCompleted.dispatch( success );
		}

		/**
		 * 
		 */
		public function request(timeout : Number = 0) : void {
			this.proxied.request( timeout );
		}

		private function handleRequestCompleted(success : Boolean) : void {
			this.signal4RequestCompleted.dispatch( success );
		}

		private function convert2AdSlot(pObj : Object) : XAdSlot {
			if (!adSlotHashMap[pObj]) {
				adSlotHashMap[pObj] = new XAdSlot( pObj );
			}
			return (adSlotHashMap[pObj] as XAdSlot);
		}

		/**
		 * 
		 */
		public function setVideoDisplayRectangle(slotRect : Rectangle, videoRect : Rectangle) : void {
			this.proxied.setVideoDisplayRectangle( slotRect, videoRect );
		}

		public function getVersion() : uint {
			return this.proxied.getVersion();
		}

		public function dispose() : void {
			this.proxied.dispose();
			//
			var pro : Object;
			for (pro in adSlotHashMap) {
				adSlotHashMap[pro].proxied = null;
				delete adSlotHashMap[pro];
			}
			proxied = null;
		}
	}
}
